#include <fstream>   // file I/O
#include <iostream>
#include <iomanip>   // format manipulation
#include <string>
#include <list>
#include <stdlib.h>
#include "matriz.h"

#define RUNTEST(t,d) { cerr << endl << "Corriendo test " << #t << ": " << #d << endl; t(); cerr << "Terminado test " << #t << " OK!" << endl << endl; }
#define dim 2
#define filas 4

using namespace std;

void test0() {
    // la copia de una matriz es independiente de otra.
    Matriz m(filas,dim);
    Matriz n(filas,dim);
    n.setPos(0,0,2);
    assert( n(0,0) != m(0,0) );
    // el operador asignacion genera matrices independientes
    Matriz o = n;
    o.setPos(0,0,3);
    assert( n(0,0) != o(0,0) );
    // testeando memoria
    Matriz *dinamica = new Matriz(10, 10);
    delete dinamica;
}

void test1(){
        Matriz m(filas,dim);
        Matriz n(filas,dim);
        Matriz res(filas,dim);
        for(int i=0; i<filas; i++) {
                for(int j=0;j<dim;j++) {
                        double mij = rand()%11+1;
                        double nij = rand()%11+1;
                        m.setPos(i,j ,mij);
                        n.setPos(i,j ,nij);
                        res.setPos(i,j,mij+nij);
                }
        }
        Matriz k = m+n;
		//Matriz k = m.suma(n);
        assert(res == k);
}


void test2(){
        Matriz m(filas,dim);
        Matriz n(filas,dim);
        Matriz res(filas,dim);
        for(int i=0;i<filas;i++) {
                for(int j=0;j<dim;j++) {
                        double mij = rand()%11+1;
                        double nij = rand()%11+1;
                        m.setPos(i, j, mij);
                        n.setPos(i, j, nij);
                        res.setPos(i, j, mij - nij);
                }
        }
        Matriz k = m-n;
        assert( res == k);
}

void test3(){
        Matriz m(filas,dim);
        Matriz res(filas,dim);
        double num= rand()%7+1;
        for(int i=0;i<filas;i++){
                for(int j=0;j<dim;j++){
                        double mij = rand()%11+1;
                        m.setPos(i,j ,mij);
                        res.setPos(i, j, num*mij);
                }
        }
        Matriz k = num*m;
        assert(res == k);
}

void test4(){
        Matriz m(filas,dim);
        Matriz n(dim,filas);
        Matriz res(filas,filas);
        for(int i=0;i<filas;i++) {
                for(int j=0;j<dim;j++) {
                        m.setPos(i,j ,rand()%11+1);
                }
        }
		for(int i=0;i<dim;i++) {
                for(int j=0;j<filas;j++) {
                        n.setPos(i,j ,rand()%11+1);
                }
        }

        for(unsigned int i = 0; i < m.n; i++){
                for(unsigned int j = 0; j < n.m; j++){
                        double temp = 0;
                        for(unsigned int k = 0; k < n.n; k++){
                                temp += m(i,k) * n(k,j);
                        }
                        res.setPos(i, j, temp);
                }
        }
}

void test5() {
        Matriz m(filas,filas);
        for(int i=0;i<filas;i++) {
                for(int j=0;j<filas;j++) {
                        m.setPos(i,j ,rand()%(23+j)+1);
                }
        }
        cout << "MATRIZ M: " << endl;
        cout << m;
        double a[filas];
        cout << "B es: [";
        for(int x = 0; x < filas; x++){
                if(x != 0)
                        cout << ", ";
                a[x] = rand()%17;
                cout << a[x];
        }
        cout << "]"<<endl;
        double b[filas];
        if(m.resolver(a,b))
                cout << "RESOLVIO!" << endl;
        else
                cout << "NO RESOLVIO :S"<< endl;
}
int main(){
    srand(time(NULL));
    RUNTEST(test0, Probando Constructores y asignacion);
    RUNTEST(test1, Probando la suma);
    RUNTEST(test2, Probando la resta);
    RUNTEST(test3, Probando multiplicacion escalar);
    RUNTEST(test4, Probando multiplicacion con matriz);
    RUNTEST(test5, Resolviendo ecuacion);
    return 0;
}


